#include "manifest.h"
#include <linux/ashmem.h>

#define ASHMEM_DEVICE	"/dev/ashmem"

int ashmem_create_region(const char *name, size_t size) {
    int fd = open(ASHMEM_DEVICE, O_RDWR);
    if (fd < 0) {
	return fd;
    }
    if (name != null) {
        assertion(strlen(name) < ASHMEM_NAME_LEN, "strlen(%s)=%d >= ", name, strlen(name), ASHMEM_NAME_LEN);
	int r = ioctl(fd, ASHMEM_SET_NAME, name);
	if (r >= 0) {
            r = ioctl(fd, ASHMEM_SET_SIZE, size);
	}
	if (r < 0) {
	    close(fd);
	    return r;
	}
    }
    return fd;
}

int ashmem_set_prot_region(int fd, int prot) {
    return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
}


/* // NOT supported on Android:

int ashmem_pin_region(int fd, size_t offset, size_t len) {
    struct ashmem_pin p = { offset, len };
    return ioctl(fd, ASHMEM_PIN, &p);
}

int ashmem_unpin_region(int fd, size_t offset, size_t len) {
    struct ashmem_pin p = { offset, len };
    return ioctl(fd, ASHMEM_UNPIN, &p);
}

int ashmem_get_pin_status(int fd, size_t offset, size_t len) {
    struct ashmem_pin p = { offset, len };
    return ioctl(fd, ASHMEM_UNPIN, &p);
}

*/

void ashmem_smoke_test() {
    for (int i = 0; i < 1000; i++) {
        char s[16];
        sprintf(s, "test%d", i);
        int fd = ashmem_create_region(s, PAGE_SIZE);
        assertion(fd > 0, "ashmem_create_region failed with file descriptor %d", fd);
        int r = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
        assertion(r == 0, "ashmem_set_prot_region failed with result %d", r);
        r = close(fd);
        assertion(r == 0, "close failed with result %d", r);
    }
}
